package com.newvpn.fastbest.zenith.utils;

import android.annotation.SuppressLint;
import android.util.Log;

import com.newvpn.fastbest.zenith.presenter.VPNDetailInfo;
import com.newvpn.fastbest.zenith.beans.netbeans.VpnInfo;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.disposables.Disposable;
import io.reactivex.rxjava3.functions.Consumer;
import io.reactivex.rxjava3.schedulers.Schedulers;

public class TestSpeedUtils {

    private int bestSpeed = 500;
    private int currIndex = 0;
    private VpnInfo.Server currFastestServer;

    public void testSpeed(List<VpnInfo> list,String errorService, Callback callback) {
        //new PingTask().execute(list);
        List<VPNDetailInfo> serverList = new ArrayList<>();
        for (VpnInfo vpnInfo : list) {
            List<VPNDetailInfo> list1 = new ArrayList<>();

            for (VpnInfo.Server server:vpnInfo.server){
                VPNDetailInfo vpnDetailInfo = new VPNDetailInfo();
                vpnDetailInfo.iconUrl = vpnInfo.iconUrl;
                vpnDetailInfo.nodeId = vpnInfo.nodeId;
                vpnDetailInfo.countryName = vpnInfo.countryName;
                vpnDetailInfo.serverId = server.serverId;
                vpnDetailInfo.serverIp = server.serverIp;
                vpnDetailInfo.serverPort = server.serverPort;
                if (errorService == null){
                    list1.add(vpnDetailInfo);
                }else if( !errorService.equals(server.serverId)){
                    list1.add(vpnDetailInfo);
                }
            }
            serverList.addAll(list1);
        }
//        List<List<VpnInfo.Server>> groupedServerList = serverList.stream()
//                .collect(Collectors.groupingBy(
//                        e -> (int) (serverList.indexOf(e) / 5), // 将元素分组
//                        Collectors.toList() // 每个分组内部使用List收集
//                ))
//                .values()
//                .stream()
//                .map(subList -> new ArrayList<>(subList)) // 防止修改原始分组
//                .collect(Collectors.toList());
        currIndex = 0;
        currFastestServer = null;
        //List<VpnInfo.Server> currList = groupedServerList.get(currIndex);
        //testOnce(serverList, callback);
        testOnce(serverList, callback);

        //findFastestServer
    }




    public interface Callback {
        void onResult(VPNDetailInfo server);
    }


    public static Observable<Object> ping(List<VPNDetailInfo> hosts, int timeout) {
        VLog.e( "start ping");
        return Observable.fromIterable(hosts)
                .flatMap(host -> Observable.create(emitter -> {
                            long startTime = System.currentTimeMillis();
                            long endTime;
                            Socket socket = null;

                            try {
                                socket = new Socket();
                                socket.connect(new InetSocketAddress(host.serverIp, host.serverPort), timeout);
                                endTime = System.currentTimeMillis() - startTime;
                                VLog.e( host.serverIp + "," + endTime);

                                // 发送数据给观察者
                                emitter.onNext(host.withPingTime(endTime));
                                emitter.onComplete();
                            } catch (IOException e) {
                                VLog.e( host.serverIp + ", Cannot reach host:");
                                endTime = Long.MAX_VALUE; // 表示连接失败或超时
                                emitter.onNext(host.withPingTime(endTime));
                                emitter.onComplete();
                            } finally {
                                if (socket != null) {
                                    try {
                                        socket.close();
                                    } catch (IOException ex) {
                                        // Ignore the close exception
                                    }
                                }
                            }
                        })
                //.subscribeOn(Schedulers.io())// 指定并发数量为 hosts 的大小
                //.filter(host -> host.getPingTime() != Long.MAX_VALUE)
                .firstElement() // 取第一个成功的结果
                .subscribeOn(Schedulers.io()).toObservable().subscribeOn(Schedulers.io()));
    }


//    public static Observable<VPNDetailInfo> ping(List<VPNDetailInfo> hosts, int timeout) {
//        Log.e("testip","start ping");
//        return Observable.fromIterable(hosts)
//                .subscribeOn(Schedulers.io())
//                .flatMap(host -> {
//                    long startTime = System.currentTimeMillis();
//                    long endTime;
//                    Socket socket = null;
//                    try {
//                        socket = new Socket();
//                        socket.connect(new InetSocketAddress(host.serverIp, host.serverPort), timeout);
//                        endTime = System.currentTimeMillis() - startTime;
//                        Log.e("testip",host.serverIp+","+endTime);
//                    } catch (IOException e) {
//                        Log.e("testip",host.serverIp+", Cannot reach host:");
//                        endTime = Long.MAX_VALUE; // 表示连接失败或超时
//                    } finally {
//                        if (socket != null) {
//                            try {
//                                socket.close();
//                            } catch (IOException e) {
//                                // Ignore the close exception
//                            }
//                        }
//                    }
//                    return Observable.just(host.withPingTime(endTime));
//                })
//                .filter(host -> host.getPingTime() != Long.MAX_VALUE)
//                .firstElement()
//                .toObservable()
//                .subscribeOn(Schedulers.io());
//    }

    Disposable testTimeDisposable;

    //    @SuppressLint("CheckResult")
    @SuppressLint("CheckResult")
    public void testOnce(List<VPNDetailInfo> list, Callback callback) {
        if (testTimeDisposable != null){
            testTimeDisposable.dispose();
        }
//        int count = 1;
//        for (VPNDetailInfo vpnDetailInfo:list){
//            count++;
//            vpnDetailInfo.serverIp = "8.8.8."+count;
//        }
        testTimeDisposable = ping(list,3*1000).subscribe(new Consumer<Object>() {
            @Override
            public void accept(Object object) throws Throwable {
                VPNDetailInfo server = (VPNDetailInfo)object;
                callback.onResult(server);
            }
        }, new Consumer<Throwable>() {
            @Override
            public void accept(Throwable throwable) throws Throwable {
                callback.onResult(null);
                throwable.printStackTrace();
            }
        });
//        Single<VpnInfo.Server> fastestServerObservable = Observable.fromIterable(list)
//                .flatMap(server -> Observable.just(server)
//                        .flatMap(s -> pingServer(s))
//                        //.timeout(3, TimeUnit.SECONDS) // 设置超时时间
//                        .onErrorReturnItem(null) // 如果ping失败，返回server对象
//                        .subscribeOn(Schedulers.io())) // 在IO线程执行ping操作
//                .sorted(Comparator.comparingLong(VpnInfo.Server::getPingTime)) // 对发射的数据进行排序
//                .firstOrError();
//        fastestServerObservable
//                .subscribe(
//                        fastestServer -> {
//                            callback.onResult(fastestServer);
//                        },
//                        printStackTrace -> {
//                            callback.onResult(null);
//                            printStackTrace.printStackTrace();
//                        }
//                );
    }



//    // 模拟ping操作的Observable
//    private static Observable<VpnInfo.Server> pingServer(VpnInfo.Server server) {
//        long pingTime = ping(server.serverIp, server.serverPort, 3 * 1000);
//        return Observable.just(server.withPingTime(pingTime));
//    }

//    public static long ping(String host, int port, int timeout) {
//        long startTime = System.currentTimeMillis();
//        long endTime;
//        Socket socket = null;
//
//        try {
//            socket = new Socket();
//            socket.connect(new InetSocketAddress(host, port), timeout);
//            endTime = System.currentTimeMillis() - startTime;
//        } catch (IOException e) {
//            System.out.println("Cannot reach host: " + host);
//            endTime = Long.MAX_VALUE; // 表示连接失败或超时
//        } finally {
//            if (socket != null) {
//                try {
//                    socket.close();
//                } catch (IOException e) {
//                    // Ignore the close exception
//                }
//            }
//        }
//        return endTime;
//    }


}
